
/*
 ************************************************************************************************
 *                                                                                              *
 *  OSA cooperative RTOS for Microchip PIC-controllers: PIC10/12/16/18/24/dsPIC                 *
 *                                                                                              *
 *  URL:            http://wiki.pic24.ru/doku.php/en/osa/ref/intro                              *
 *                  http://picosa.narod.ru                                                      *
 *                                                                                              *
 *----------------------------------------------------------------------------------------------*
 *                                                                                              *
 *  File:           osa_mcc18.h                                                                 *
 *                                                                                              *
 *  Compilers:      HT-PICC STD                                                                 *
 *                  HT-PICC18 STD                                                               *
 *                  Microchip C18                                                               *
 *                  Microchip C30                                                               *
 *                                                                                              *
 *  Programmer:     Timofeev Victor                                                             *
 *                  osa@pic24.ru, testerplus@mail.ru                                            *
 *                                                                                              *
 *  Description:    MCC18 specific definitions                                                  *
 *                                                                                              *
 *                                                                                              *
 ************************************************************************************************
 */

#ifndef __OSAMCC18_H__
#define __OSAMCC18_H__



/************************************************************************************************
 *                                                                                              *
 *     Registers definitions                                                                    *
 *                                                                                              *
 ************************************************************************************************/

extern          near unsigned char      TOSL;
extern          near unsigned char      TOSH;
extern          near unsigned char      TOSU;
extern volatile near unsigned char      STKPTR;
extern volatile near unsigned char      INTCON;
extern volatile near unsigned char      RCON;


#define _fsr        FSR0
#define _indf       INDF0
#define _postinc    POSTINC0
#define _postdec    POSTDEC0
#define _preinc     PREINC0


#define _postinc1   POSTINC1
#define _postdec1   POSTDEC1
#define _indf1      INDF1
#define _fsr1l      FSR1L
#define _fsr2l      FSR2L

#define _pcl        PCL
#define _pclath     PCLATH
#define _pclatu     PCLATU
#define _status     STATUS
#define _tosh       TOSH
#define _tosl       TOSL
#define _tosu       TOSU
#define _bsr        BSR
#define _wreg       WREG
#define _stkptr     STKPTR
#define _intcon     INTCON
#define _rcon       RCON






/************************************************************************************************
 *                                                                                              *
 *     Constants and types                                                                      *
 *                                                                                              *
 ************************************************************************************************/

#ifndef OS_SMSG_SIZE
#define OS_SMSG_SIZE    0   // We can not use sizeof() because it does not work with #ifdef directive
#endif


#define _PIC18_ERRATA_NOP()  _asm nop _endasm
#define _PIC18_POP()         _asm pop _endasm
#define _SET_TASK_IRP()      // Empty macro (used only for PIC16)

typedef unsigned int            _FSR_TYPE;

// Code pointer (used in OST_TCB)

//------------------------------------------------------------------------------
#if defined(__SMALL__)
//------------------------------------------------------------------------------

    typedef unsigned int            OST_CODE_POINTER;
    #define OS_CODE_POINTER_SIZE    2

//------------------------------------------------------------------------------
#else
//------------------------------------------------------------------------------

    typedef unsigned long           OST_CODE_POINTER;
    #define OS_CODE_POINTER_SIZE    4

//------------------------------------------------------------------------------
#endif
//------------------------------------------------------------------------------








/************************************************************************************************
 *                                                                                              *
 *     Platform macros                                                                          *
 *                                                                                              *
 ************************************************************************************************/

#define OS_CLRWDT()   _asm clrwdt   _endasm
#define OS_ClrWdt()   _asm clrwdt   _endasm
#define OS_SLEEP()    _asm sleep    _endasm
#define OS_Sleep()    _asm sleep    _endasm







/************************************************************************************************
 *                                                                                              *
 *     Context switching macros                                                                 *
 *                                                                                              *
 ************************************************************************************************/


//------------------------------------------------------------------------------
// Save/restore PC macros
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
#if defined(__SMALL__)
//------------------------------------------------------------------------------

    #define _OS_SetPC()             _pclath = _postdec;         \
                                    _asm                        \
                                        movf    _postdec, 0, 0  \
                                        movwf   _pcl, 0         \
                                    _endasm


    #define _OS_SavePC()            _postdec = _tosh;           \
                                    _postdec = _tosl;

//------------------------------------------------------------------------------
#else
//------------------------------------------------------------------------------

    #define _OS_SetPC()             _postdec = 0;               \
                                    _pclatu = _postdec;         \
                                    _pclath = _postdec;         \
                                    _asm                        \
                                        movf    _postdec, 0, 0  \
                                        movwf   _pcl, 0         \
                                    _endasm

    #define _OS_SavePC()            _postdec = 0;               \
                                    _postdec = _tosu;           \
                                    _postdec = _tosh;           \
                                    _postdec = _tosl;

//------------------------------------------------------------------------------
#endif
//------------------------------------------------------------------------------




/*
 ********************************************************************************
 *                                                                              *
 *  _OS_JumpToTask()                                                            *
 *                                                                              *
 *------------------------------------------------------------------------------*
 *                                                                              *
 *  description:        jump indirectly from kernel (OS_Sched) into task        *
 *                                                                              *
 ********************************************************************************
 */


#define _OS_JumpToTask()                                                    \
    {                                                                       \
        _OS_SET_FSR_CUR_TASK_W(OS_CODE_POINTER_SIZE+1);                     \
        _asm                                                                \
            bra     _OS_call_indirrect                                      \
    _OS_jump_indirrect:                                                     \
        _endasm                                                             \
        if (_indf) {                                                        \
            _indf1 = _fsr2l;                                                \
            _fsr2l = _fsr1l + 1;                                            \
        }                                                                   \
        _OS_tempH = _fsr1l;                                                 \
        _fsr1l += _postdec;                                                 \
        _OS_SetPC();                                                        \
        /* Now FSR points to OS_CurTask->State    */                        \
        _asm                                                                \
    _OS_call_indirrect:                                                     \
            rcall   _OS_jump_indirrect                                      \
        _endasm                                                             \
        if (_fsr1l != _OS_tempH) {                                          \
            _fsr1l = _OS_tempH;                                             \
            _fsr2l = _indf1;                                                \
        }                                                                   \
    }

#define _OS_SaveRetAddr()

#define _OS_if_Ready()  _OS_SET_FSR_CUR_TASK();                             \
                        if (_OS_bTaskReady)






/************************************************************************************************
 *                                                                                              *
 *     Return from task to OS_Sched macros                                                      *
 *                                                                                              *
 ************************************************************************************************/


/*
 ********************************************************************************
 *                                                                              *
 *   Switch control routines:                                                   *
 *                                                                              *
 *    _OS_GetReturnPoint()                - exit from task and save context     *
 *                                                                              *
 *    _OS_ReturnNoSave()                  - exit withowt saving return address  *
 *                                                                              *
 *    _OS_CLEAR_READY()                   - exit with saving address and        *
 *                                          clearing bReady                     *
 *                                                                              *
 *    _OS_CLEAR_READY_SET_CANCONTINUE()   - exit without saving address and     *
 *                                          clearing bReady and bCanContinue    *
 *                                                                              *
 ********************************************************************************
 */


extern void OS_SchedRetPoint (void);
extern void OS_SchedRetPointNoSave (void);
extern void OS_ClearReady (void);
extern void OS_ClearReadySetCanContinue (void);

extern void  __OS_SET_FSR_CUR_TASK_W (void);
extern void  _OS_SET_FSR_CUR_TASK (void);

#define _OS_SET_FSR_CUR_TASK_W(w)               \
    {   _wreg = w;                              \
        __OS_SET_FSR_CUR_TASK_W();              \
    }


//------------------------------------------------------------------------------
#define _OS_GetReturnPoint()        {                                           \
                                        OS_SchedRetPoint();                     \
                                        _PIC18_ERRATA_NOP();                    \
                                    }

//------------------------------------------------------------------------------
#define _OS_CLEAR_READY()           {                                           \
                                        OS_ClearReady();                        \
                                        _PIC18_ERRATA_NOP();                    \
                                    }

//------------------------------------------------------------------------------
#define _OS_CLEAR_READY_SET_CANCONTINUE()                                       \
                                    {                                           \
                                        OS_ClearReadySetCanContinue();          \
                                        _PIC18_ERRATA_NOP();                    \
                                    }

//------------------------------------------------------------------------------
#define _OS_ReturnNoSave()          {                                           \
                                        OS_SchedRetPointNoSave();               \
                                        _PIC18_ERRATA_NOP();                    \
                                    }                                           \

//------------------------------------------------------------------------------






















/******************************************************************************************
 *
 *  WORK WITH DYNAMIC TIMERS
 *
 ******************************************************************************************/

//------------------------------------------------------------------------------
#ifdef OS_ENABLE_DTIMERS
//------------------------------------------------------------------------------


//------------------------------------------------------------------------------
#if   OS_DTIMER_SIZE == 1
//------------------------------------------------------------------------------

    #define OS_INC_DTIMER()                                                             \
        {                                                                               \
            _asm                                                                        \
                movlw   3                                                               \
                addwf   _fsr, 1, 0                                                      \
                incf    _postdec, 1, 0  /* FSR0L can't overflow here */                 \
                movf    _postdec, 0, 0                                                  \
                movf    _postdec, 0, 0                                                  \
            _endasm                                                                     \
            if (_status & 0x01) _OS_SetIndfTimerTimeout;                                \
        }


//------------------------------------------------------------------------------
#elif OS_DTIMER_SIZE == 2
//------------------------------------------------------------------------------

    #define OS_INC_DTIMER()                                                             \
        {                                                                               \
            _OS_DTimers.Flags.bTimeout = 0;                                             \
            _asm                                                                        \
                movlw   3                                                               \
                addwf   _fsr, 1, 0                                                      \
                movlw   0                                                               \
                incf    _postinc, 1, 0                                                  \
                addwfc  _postdec, 1, 0                                                  \
            _endasm                                                                     \
            if (_status & 0x01) _OS_DTimers.Flags.bTimeout = 1;                         \
            _asm                                                                        \
                movlw   3                                                               \
                subwf   _fsr, 1, 0                                                      \
            _endasm                                                                     \
            if (_OS_DTimers.Flags.bTimeout)                                             \
                _OS_SetIndfTimerTimeout;                                                \
        }

//------------------------------------------------------------------------------
#elif OS_DTIMER_SIZE == 4
//------------------------------------------------------------------------------

    #define OS_INC_DTIMER()                                                             \
        {                                                                               \
            _OS_DTimers.Flags.bTimeout = 0;                                             \
            _asm                                                                        \
                movlw   3                                                               \
                addwf   _fsr, 1, 0                                                      \
                movlw   0                                                               \
                incf    _postinc, 1, 0                                                  \
                addwfc  _postinc, 1, 0                                                  \
                addwfc  _postinc, 1, 0                                                  \
                addwfc  _postdec, 1, 0                                                  \
            _endasm                                                                     \
            if (_status & 0x01) _OS_DTimers.Flags.bTimeout = 1;                         \
            _asm                                                                        \
                movlw   5                                                               \
                subwf   _fsr, 1, 0                                                      \
            _endasm                                                                     \
            if (_OS_DTimers.Flags.bTimeout)                                             \
                _OS_SetIndfTimerTimeout;                                                \
        }

//------------------------------------------------------------------------------
#endif
//------------------------------------------------------------------------------


#define __OS_DTimersWork()                              \
    {                                                   \
        _fsr = (_FSR_TYPE) &_OS_DTimers.Flags;          \
    REPEAT:                                             \
        if (_OS_CheckPostincTimerNextEnable)            \
        {                                               \
            /* Point FSR to next timer           */     \
            _asm                                        \
                movf    _postinc, 0, 0                  \
                movff   _postdec, _fsr + 1              \
                movwf   _fsr + 0, 0                     \
            _endasm                                     \
            if (!_OS_CheckIndfTimerRun) goto REPEAT;    \
            OS_INC_DTIMER();                            \
            goto REPEAT;                                \
        }                                               \
    }



//------------------------------------------------------------------------------
#endif  // OS_ENABLE_DTIMER
//------------------------------------------------------------------------------






#endif















